package impl;

import java.util.Date;

import java.util.Random;

import api.IAuthenticator;
import api.IPostman;
import api.ISocializer.MessageBoardsType;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import entities.Login;
import entities.Messageboard;
import entities.Userprofile;

/**
 * Session Bean implementation class Authenticator
 */
@Stateless(name = "IAuthenticator")
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
public class Authenticator implements IAuthenticator {
	@PersistenceContext(unitName = "PhaseBookPU")
	EntityManager em;

	@EJB(beanName = "IPostman")
	IPostman postman;

	/**
	 * Default constructor.
	 */
	public Authenticator() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public boolean registerUser(String username, String password) {
		System.out.println("*** AUTHENTICATOR ***");
		System.out.println("*** New User request ***");

		Query query = em.createNamedQuery("getUserProfile");
		query.setParameter("email", username);

		Userprofile userProfile = null;
		try {
			userProfile = (Userprofile) query.getSingleResult();
			if (userProfile != null)
				return false;

		} catch (NoResultException e) {

		}

		// Create a new user
		Userprofile user = new Userprofile();
		user.setEmail(username);
		em.persist(user);

		userProfile = (Userprofile) query.getSingleResult();

		// Create a login
		Login login = new Login();
		login.setUserprofile(userProfile);
		login.setPasswordHashed(hash(password));
		login.setLastAccess(new Date());
		em.persist(login);

		System.out.println("*** New User created ***");

		// Create a public user message board
		Messageboard msgBoard = new Messageboard();
		msgBoard.setUserprofile(userProfile);
		msgBoard.setType(MessageBoardsType.PUBLIC.ordinal());
		em.persist(msgBoard);

		// Create a private user message board
		msgBoard = new Messageboard();
		msgBoard.setUserprofile(userProfile);
		msgBoard.setType(MessageBoardsType.PRIVATE.ordinal());
		em.persist(msgBoard);

		postman.sendMail(user.getEmail(), "Registration complete",
				"Welcome to PhaseBook!\n Your registration is complete.");

		return true;
	}

	@Override
	public boolean authenticate(String username, String password) {
		System.out.println("*** AUTHENTICATOR ***");
		System.out.println("*** Validate User request ***");

		Query query = em.createNamedQuery("validateUserLoggin");
		query.setParameter("email", username);
		query.setParameter("pass", hash(password));

		Integer userId = (Integer) query.getSingleResult();

		query = em.createNamedQuery("getUserLoggin");
		query.setParameter("email", username);
		Login login = (Login) query.getSingleResult();
		login.setLastAccess(new Date());
		em.persist(login);

		System.out.println("*** User " + username + " validated with id: "
				+ userId.intValue() + " ***");
		return true;
	}

	@Override
	public Date getLastLogin(String username) {
		System.out.println("*** AUTHENTICATOR ***");
		System.out.println("*** Last User Login request ***");

		Query query = em.createNamedQuery("getUserLogginLastAccess");
		query.setParameter("email", username);

		return (Date) query.getSingleResult();
	}

	@Override
	public boolean resetPassword(String username) {
		System.out.println("*** AUTHENTICATOR ***");
		System.out.println("*** Reset User Password ***");

		Query query = em.createNamedQuery("getUserLoggin");
		query.setParameter("email", username);

		Login login = (Login) query.getSingleResult();
		String newPass = generateString();
		login.setPasswordHashed(hash(newPass));
		em.persist(login);

		String message = "Hi " + username + "\n\n"
				+ "You performed a password reset.\n" + "The new password is'"
				+ newPass + "'";

		postman.sendMail(username, "Reset Password", message);

		return true;
	}

	private String hash(String string) {
		long h = 1125899906842597L; // prime
		int len = string.length();

		for (int i = 0; i < len; i++) {
			h = 31 * h + string.charAt(i);
		}
		return "" + h;
	}

	public String generateString() {
		Random rng = new Random();
		String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		int length = 8;

		char[] text = new char[length];
		for (int i = 0; i < length; i++) {
			text[i] = characters.charAt(rng.nextInt(characters.length()));
		}
		return new String(text);
	}
}
